package com.uvnos4j.matilda.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.uvnos4j.matilda.commons.utils.TreeUtil;
import com.uvnos4j.matilda.system.domain.SysAcl;
import com.uvnos4j.matilda.system.domain.SysRoleAcl;
import com.uvnos4j.matilda.system.domain.SysUser;
import com.uvnos4j.matilda.system.domain.SysUserRole;
import com.uvnos4j.matilda.system.mapper.SysAclMapper;
import com.uvnos4j.matilda.system.mapper.SysRoleAclMapper;
import com.uvnos4j.matilda.system.mapper.SysUserMapper;
import com.uvnos4j.matilda.system.mapper.SysUserRoleMapper;
import com.uvnos4j.matilda.system.service.SysAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 系统authService实现
 *
 * @author Guo.wl
 */
@Service
@Transactional(readOnly = true)
public class SysAuthServiceImpl implements SysAuthService {

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleAclMapper sysRoleAclMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Override
    public List<SysAcl> buildRoleAclTree(SysUser user, Long roleId) {
        // 获取当前登录用户拥有权限
        List<SysAcl> userAclList = sysAclMapper.findByUserId(user.getId());
        // 获取所选角色的权限
        List<SysAcl> roleAclList = sysAclMapper.findByRoleId(roleId);

        List<Long> userAclIdList = new ArrayList<>();
        for (SysAcl acl : userAclList) {
            userAclIdList.add(acl.getId());
        }
        List<Long> roleAclIdList = new ArrayList<>();
        for (SysAcl acl : roleAclList) {
            roleAclIdList.add(acl.getId());
        }

        // 获取所有权限
        LambdaQueryWrapper<SysAcl> lqw = new LambdaQueryWrapper<>();
        lqw.orderByAsc(SysAcl::getSeq);
        List<SysAcl> allAclList = sysAclMapper.selectList(lqw);
        for (SysAcl acl : allAclList) {
            if (user.isAdmin() || userAclIdList.contains(acl.getId())) {
                // 标识用户拥有的权限
                acl.setHasAcl(true);
            }
            if (roleAclIdList.contains(acl.getId())) {
                // 标识角色拥有的权限
                acl.setChecked(true);
            }
        }
        return TreeUtil.bulidTree(allAclList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRoleAcls(Long roleId, List<Long> aclIdList) {
        // 查询角色原有权限
        List<SysAcl> roleAclList = sysAclMapper.findByRoleId(roleId);
        List<Long> beforeAclIdList = new ArrayList<>();
        for (SysAcl acl : roleAclList) {
            beforeAclIdList.add(acl.getId());
        }

        // 新权限与原来相同时
        if (isSame(beforeAclIdList, aclIdList)) {
            return;
        }

        // 新权限与原来数目相同且权限有变化时，或者新权限与原来数目不相同时
        LambdaQueryWrapper<SysRoleAcl> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysRoleAcl::getRoleId, roleId);
        sysRoleAclMapper.delete(lqw);

        for (Long aclId : aclIdList) {
            SysRoleAcl roleAcl = new SysRoleAcl();
            roleAcl.setRoleId(roleId);
            roleAcl.setAclId(aclId);
            sysRoleAclMapper.insert(roleAcl);
        }
    }

    @Override
    public List<SysUser> findRoleUserList(Long roleId) {
        return sysUserMapper.findByRoleId(roleId);
    }

    @Override
    public List<SysUser> findRoleNoUserList(Long roleId) {
        List<SysUser> allUserList = sysUserMapper.selectList(null);
        List<SysUser> roleUserList = sysUserMapper.findByRoleId(roleId);
        allUserList.removeAll(roleUserList);
        return allUserList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveRoleUsers(Long roleId, List<Long> userIdList) {
        // 查询角色原有用户
        List<SysUser> roleUserList = sysUserMapper.findByRoleId(roleId);
        List<Long> beforeUserIdList = new ArrayList<>();
        for (SysUser user : roleUserList) {
            beforeUserIdList.add(user.getId());
        }

        // 新用户与原来相同时
        if (isSame(beforeUserIdList, userIdList)) {
            return;
        }

        // 新用户与原来数目相同且权限有变化时，或者新用户与原来数目不相同时
        LambdaQueryWrapper<SysUserRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysUserRole::getRoleId, roleId);
        sysUserRoleMapper.delete(lqw);

        for (Long userId : userIdList) {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            sysUserRoleMapper.insert(userRole);
        }
    }

    /**
     * 判断两个list集合是否相同
     *
     * @param oldList list1
     * @param newList list2
     * @param <T>     T
     * @return true相同；false不同
     */
    private <T> boolean isSame(List<T> oldList, List<T> newList) {
        // 新用户与原来数目相同时
        if (oldList.size() == newList.size()) {
            // 原用户id的set集合
            Set<T> oldSet = new HashSet<>(oldList);
            // 新用户id的set集合
            Set<T> newSet = new HashSet<>(newList);
            oldSet.removeAll(newSet);
            // 权限无变化
            return oldSet.isEmpty();
        }
        return false;
    }

}